#include "StdAfx.h"
#include "CustomActionHelpers.h"

using namespace FusionWare::MSI;

void Session::LogMsg(const TCHAR* Msg, bool ThrowOnFail)
{
    PMSIHANDLE hRecord = MsiCreateRecord(1);

    ::MsiRecordSetString(hRecord, 0, Msg);

    UINT er = ::MsiProcessMessage(this->hInstall, INSTALLMESSAGE_INFO, hRecord);
	if(ThrowOnFail && (ERROR_INSTALL_USEREXIT == er || IDCANCEL == er))
        throw FusionWare::MSI::Exception(_T("Log ERROR"), er);
}

void Session::LogMsg(_bstr_t Msg, bool ThrowOnFail)
{
    PMSIHANDLE hRecord = MsiCreateRecord(1);

    ::MsiRecordSetString(hRecord, 0, Msg);

    UINT er = ::MsiProcessMessage(this->hInstall, INSTALLMESSAGE_INFO, hRecord);
	if(ThrowOnFail && (ERROR_INSTALL_USEREXIT == er || IDCANCEL == er))
        throw FusionWare::MSI::Exception(_T("Log ERROR"), er);
}

CString Session::GetProperty(const TCHAR* Name)
{
    CString retVal;
    DWORD cchValueBuf = 0;
    UINT err =  MsiGetProperty(this->hInstall, Name, _T(""), &cchValueBuf);
    if( ERROR_MORE_DATA == err )
    {
        ++cchValueBuf; // on output does not include terminating null, so add 1
        TCHAR* pBuf = retVal.GetBufferSetLength((int)cchValueBuf);
        if(pBuf == NULL)
            throw FusionWare::MSI::OutOfMemory;

        err = MsiGetProperty(this->hInstall, Name, pBuf, &cchValueBuf);
        retVal.ReleaseBuffer();
    }
    if( ERROR_SUCCESS != err )
        throw FusionWare::MSI::Exception(_T("Could not retrieve property data"), ERROR_INSTALL_FAILURE);
    
    return retVal;
}

std::vector<CString> Session::GetCustomActionData(unsigned MinArgs, const TCHAR* pDelimiter)
{
    std::vector<CString> argv;
    CString customData = GetProperty(_T("CustomActionData"));

    //  split the string based on the delimiter
    for(int start=0; start >= 0; )
        argv.push_back(customData.Tokenize(pDelimiter, start));

    if( MinArgs > 0  && argv.size() < MinArgs )
        throw FusionWare::MSI::Exception(_T("Incorrect number of arguments found in CustomActionData!"), ERROR_BAD_ARGUMENTS);

    return argv;
}

UINT Session::DoCustomAction(CaFunc Action)
{
    try 
    {
        Action(*this);
        return ERROR_SUCCESS;
    }
    catch( FusionWare::MSI::Exception e )
    {
        LogMsg(e.Msg, false);
        return e.Error;
    }
    catch( std::bad_alloc e )
    {
        LogMsg(_T("Out of Memory"),false);
        return ERROR_NOT_ENOUGH_MEMORY;
    }
    catch( _com_error e )
    {
        _bstr_t desc = e.Description();
        LogMsg(desc, false); // block exception on fail to log
        return e.Error();
    }
}

